#include "EpilFunctionBodyParser.h"
#include "EpilParserException.h"
#include "EpilParameterListParser.h"
#include "EpilChunkParser.h"
#include "EpilPointerHelper.h"


EpilFunctionBodyParser::EpilFunctionBodyParser( EpilTokenStream & tokens )
: EpilSyntaxParserBase( tokens )
{
}


void EpilFunctionBodyParser::Parse()
{
	// body -> `(' parlist `)' chunk END
	m_body = new EpilFunctionBodyExpressionCode( this->GetTokens().GetCurrentToken().location );

	// (
	if( this->GetTokens().GetCurrentToken().type != ETT_OpenParenthese )
	{
		EpilPointerHelper::SafeDelete( m_body );
		throw EpilParserException( t("\'(\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();

	// parlist
	EpilParameterListParser parListParser( this->GetTokens() );
	try
	{
		parListParser.Parse();
	}
	catch( ... )
	{
		EpilPointerHelper::SafeDelete( m_body );
		throw;
	}
	m_body->SetParameterList( parListParser.GetParameterList() );

	// )
	if( this->GetTokens().GetCurrentToken().type != ETT_CloseParenthese )
	{
		EpilPointerHelper::SafeDelete( m_body );
		throw EpilParserException( t("\')\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();

	// chunk
	EpilChunkParser chunkParser( this->GetTokens() );
	try
	{
		chunkParser.Parse();
	}
	catch( ... )
	{
		EpilPointerHelper::SafeDelete( m_body );
		throw;
	}
	m_body->SetChunk( chunkParser.GetChunk() );

	// END
	if( this->GetTokens().GetCurrentToken().type != ETT_KwEnd )
	{
		EpilPointerHelper::SafeDelete( m_body );
		throw EpilParserException( t("\'end\' expected."), this->GetTokens().GetCurrentToken().location );
	}
	this->GetTokens().MoveToNext();
}